package ru.dc.gui.swing;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jdesktop.swingx.JXTable;
import ru.dc.Application;
import ru.dc.ConnectionManager;
import ru.dc.object.DownloadItem;
import ru.dc.object.HubEventListener;
import ru.dc.object.ServerInfo;
import ru.dc.object.UserInfo;
import ru.dc.object.events.hub.*;

import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Style;
import javax.swing.text.StyledDocument;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: deady
 * Date: 08.10.2010
 * Time: 22:32:20
 */
public class HubConnectionController {

    private ServerInfo serverInfo;
    private SingleHubWindow frame;

    public HubConnectionController(final ServerInfo serverInfo) throws HeadlessException {

        this.serverInfo = serverInfo;
        frame = new SingleHubWindow();


        frame.addSendMessageListener(new SendMessageListener() {
            public void onMessageSend(String message) {
                Application.getApplication().getConnectionManager().chat(serverInfo, message);
            }
        });


        //добавляем обработчик нажатия мыши на список пользователей
        frame.getUsers().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                final JXTable users = frame.getUsers();
                int row = users.rowAtPoint(e.getPoint());
                int modelRow = users.convertRowIndexToModel(row);
                UsersModel model = (UsersModel) users.getModel();
                final UserInfo userInfo = model.getUsers().get(modelRow);

                //двойной клик левой кнопкой запрашивает список файлов
                if (e.getClickCount()==2 && SwingUtilities.isLeftMouseButton(e)) {
                    requestFileList(userInfo, serverInfo);
                }
                //клик правой кнопкой отобоажает всплывающее меню
                else if (SwingUtilities.isRightMouseButton(e)) {

                    //выбираем строку, на которой была нажата клавиша мыши
                    users.getSelectionModel().setSelectionInterval(row, row);
                    
                    String text = "<html>Имя: "+userInfo.getNick()+"<br>"+
                            "Скорость: "+ userInfo.getSpeed()+"<br>"+
                            "Размер файлов: "+ FileUtils.byteCountToDisplaySize(userInfo.getSharesize())+"</html>"; 

                    JPopupMenu popupMenu = new JPopupMenu();
                    final JLabel jLabel = new JLabel(text);
                    popupMenu.add(jLabel);
                    popupMenu.addSeparator();

                    JMenuItem files = new JMenuItem("Список файлов");
                    files.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            requestFileList(userInfo, serverInfo);
                        }
                    });
                    popupMenu.add(files);

                    JMenuItem chat = new JMenuItem("Чат");
                    chat.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            Application.getApplication().getMainFrame().openPrivateChatWindow(userInfo.getNick(), serverInfo);
                        }
                    });
                    popupMenu.add(chat);



                    popupMenu.show(users, e.getX(), e.getY());
                }
            }
        });



        Application.getApplication().getHubEventsTranslator().addEventListener(new HubEventListener() {

            public void onEvent(HubEvent e) {

                if (e.getServerInfo()!=HubConnectionController.this.serverInfo) {
                    return;
                }

                if (e instanceof ChatEvent) {
                    ChatEvent cmd = (ChatEvent) e;
                    addText(cmd.getNick(), cmd.getMessage());
                }

                else if (e instanceof UserLeaved) {
                    final UserLeaved cmd = (UserLeaved) e;
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            UsersModel model = (UsersModel) frame.getUsers().getModel();
                            model.removeUser(cmd.getNick());
                            //addText("User "+cmd.getNick()+" logged out >>>");
                        }
                    });
                }

                else if (e instanceof UserEntered) {
                    final UserEntered myINFO = (UserEntered) e;
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            UsersModel model = (UsersModel) frame.getUsers().getModel();
                            model.addUser(myINFO.getUserInfo());
                            //addText("User "+myINFO.getNick()+" logged in <<<");
                        }
                    });
                }

                else if (e instanceof HubNameRecieved) {
                    final HubNameRecieved hubName = (HubNameRecieved) e;
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            frame.setTitle(hubName.getName());
                        }
                    });
                }

                else if (e instanceof TopicChanged) {
                    final TopicChanged hubName = (TopicChanged) e;
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            frame.getTopic().setText(hubName.getTopic());
                        }
                    });
                }

                else if (e instanceof RecievedNickList) {
                    final RecievedNickList nickList = (RecievedNickList) e;
                    final Set<String> users = new TreeSet<String>(Arrays.asList(nickList.getUsers()));
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            UsersModel model = (UsersModel) frame.getUsers().getModel();
                            for (String user : users) {
                                UserInfo userInfo = new UserInfo();
                                userInfo.setNick(user);
                                model.addUser(userInfo);
                            }
                        }
                    });
                }
            }

        });

        frame.getReconnectBtn().addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                UsersModel model = (UsersModel) frame.getUsers().getModel();
                model.clear();
                frame.getTopic().setText("");
                frame.setTitle(serverInfo.getAddress());
                addText("Reconnecting...");
                new Thread() {
                    @Override
                    public void run() {
                        Application.getApplication().getConnectionManager().reconnect(serverInfo);
                    }
                }.start();
            }
        });

        frame.getDisconnectBtn().addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Application.getApplication().getConnectionManager().removeConnection(serverInfo);
                frame.getReconnectBtn().setEnabled(false);
                frame.getMessage().setEnabled(false);
                frame.getSendMessageBtn().setEnabled(false);
                frame.getDisconnectBtn().setEnabled(false);
                frame.getUsers().setEnabled(false);
            }
        });


    }

    private void requestFileList(UserInfo userInfo, ServerInfo serverInfo) {
        final DownloadItem item = new DownloadItem();
        item.getSource().setNick(userInfo.getNick());
        item.getSource().setHub(serverInfo);
        item.setFilename("files.xml.bz2");

        Application.getApplication().getDownloadQueue().enqueueItem(item);
    }


    public void init() {
        //инициалзиация формы
        final ConnectionManager connectionManager = Application.getApplication().getConnectionManager();
        //если для хаба установлено имя (например, окно было закрыто, а затем открыто заново, хотя соединение не
        // закрывалось), то установим его
        final String name = connectionManager.getName(serverInfo);
        if (!StringUtils.isEmpty(name)) {
            frame.setTitle(name);
        }

        //если для хаба установлена тема (например, окно было закрыто, а затем открыто заново, хотя соединение не
        // закрывалось), то установим ее
        final String topic = connectionManager.getTopic(serverInfo);
        if (!StringUtils.isEmpty(topic)) {
            frame.getTopic().setText(topic);
        }

        //если у хаба уже были загружены пользователи, добавим их в список пользователей
        Set<UserInfo> users = new HashSet<UserInfo>(connectionManager.getUsers(serverInfo));
        UsersModel model = (UsersModel) frame.getUsers().getModel();
        model.addUsers(users);

    }

    private void addText(final String text) {
        String date = new SimpleDateFormat("[HH:mm:ss]").format(new Date());
        final String message = date+" * "+text+"\n";
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getOutput().append(message);
                frame.getOutput().scrollRectToVisible(new Rectangle(0, frame.getOutput().getHeight()-2, 1, 1));
                frame.alert();
            }
        });
    }

    private void addText(String user, final String text) {
        String date = new SimpleDateFormat("[HH:mm:ss]").format(new Date());
        final String message = date+" <"+user+"> "+text+"\n";
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getOutput().append(message);
                frame.getOutput().scrollRectToVisible(new Rectangle(0, frame.getOutput().getHeight()-2, 1, 1));
                frame.alert();
            }
        });
    }

    public Tab getContent() {
        return frame;
    }

}
